Skip to content

01 Linux 哲学核心思想 - 一切皆文件

一切皆文件的含义

  • 一切皆文件:Everything is a file.
  • 无论是目录、字符设备、块设备、套接字、进程、线程,均可通过 fopen()fread()fwrite()fclose() 等函数进行处理
  • Linux 系统屏蔽了硬件的区别,将所有设备都抽象为文件,以文件的形式进行保存和管理,给用户提供统一的接口
  • 可跨文件系统执行文件读写等操作

  1. 文件:在 Linux 中,文件不仅仅是我们通常理解的文本或数据文档,它还包括设备、管道、套接字等。

    • 设备文件:硬件设备(如硬盘、终端、网络接口等)都被映射为文件,通常位于 /dev 目录中。例如,硬盘设备文件可能是 /dev/sda,终端设备文件可能是 /dev/tty1
    • 目录:目录本身也是一种文件,它存储了该目录下的文件名及其相关的元数据。
    • 进程:每个运行中的进程都在 /proc 目录中对应一个文件夹,通过这些文件夹,可以查看和操作进程的状态、内存使用、打开的文件描述符等信息。
    • 管道和套接字:用于进程间通信的管道(pipe)和网络通信使用的套接字(socket)也可以作为文件来访问。这些通常位于 /dev/proc 目录下,或者通过命名管道创建。
    • 配置文件:系统配置、用户配置等信息通常以文本文件的形式存在,便于编辑和管理。
  2. 统一视角:Linux 将几乎所有资源(如硬件设备、输入/输出接口、通信接口等)都视为文件。这意味着,对这些资源的操作可以通过标准的文件操作接口(打开、读取、写入、关闭)来完成。

  3. 文件系统:所有这些“文件”都组织在文件系统中,即使它们并不实际存储在硬盘上。

文件分类

文件类型符号描述
常规文件(Regular File)-普通的数据文件,可以包含文本、二进制数据或程序等。
目录(Directory)d包含其他文件的容器,实际上也是一种文件。
字符设备文件(Character Device)c提供对设备的串行访问,如键盘、鼠标等。
块设备文件(Block Device)b表示设备的随机访问接口,如硬盘。
管道文件(FIFO/Named Pipe)p用于进程间通信的特殊文件,数据进一端出另一端。
符号链接文件(Symbolic Link)l引用另一个文件的路径链接。
套接字文件(Socket)s用于进程间或网络间的通信,支持数据交换。

ls -lha 中输出列表信息的首字符,即代表该文件的类型

bash
  ~ ls -lha /
total 76K
dr-xr-xr-x.  20 root root 4.0K Aug  9 06:25 .
dr-xr-xr-x.  20 root root 4.0K Aug  9 06:25 ..
dr-xr-xr-x.   2 root root 4.0K Jun 25 22:23 afs
-rw-r--r--    1 root root    0 Jul 23 09:11 .autorelabel
lrwxrwxrwx    1 root root    7 Jun 25 22:23 bin -> usr/bin
dr-xr-xr-x.   5 root root 4.0K Jul 23 11:25 boot
drwxr-xr-x    2 root root 4.0K Feb  9  2022 data
drwxr-xr-x   19 root root 3.1K Jun 25 22:23 dev
drwxr-xr-x.  93 root root 4.0K Jul 31 16:07 etc
drwxr-xr-x.   3 root root 4.0K Jun 25 22:23 home
lrwxrwxrwx    1 root root    7 Jun 25 22:23 lib -> usr/lib
lrwxrwxrwx    1 root root    9 Jun 25 22:23 lib64 -> usr/lib64
drwx------.   2 root root  16K Jan 20  2022 lost+found
drwxr-xr-x.   2 root root 4.0K Jun 25 22:23 media
drwxr-xr-x.   2 root root 4.0K Jun 25 22:23 mnt
drwxr-xr-x.   2 root root 4.0K Jun 25 22:23 opt
dr-xr-xr-x  190 root root    0 Jul 23 09:11 proc
dr-xr-x---.   9 root root 4.0K Aug  9 06:25 root
drwxr-xr-x   28 root root 1000 Jul 23 12:19 run
lrwxrwxrwx    1 root root    8 Jun 25 22:23 sbin -> usr/sbin
drwxr-xr-x.   2 root root 4.0K Jun 25 22:23 srv
dr-xr-xr-x   13 root root    0 Jul 23 11:22 sys
drwxrwxrwt.   8 root root 4.0K Aug  9 06:24 tmp
drwxr-xr-x.  12 root root 4.0K Jul 23 11:22 usr
drwxr-xr-x.  19 root root 4.0K Jul 23 11:22 var
  • -rw-r--r--:常规文件(Regular File),这里的 - 表示常规文件。
  • drwxr-xr-x:目录(Directory),这里的 d 表示这是一个目录。
  • crw-rw----:字符设备文件(Character Device),这里的 c 表示字符设备。
  • brw-rw----:块设备文件(Block Device),这里的 b 表示块设备。
  • prw-r--r--:管道文件(FIFO/Named Pipe),这里的 p 表示管道。
  • lrwxrwxrwx:符号链接文件(Symbolic Link),这里的 l 表示符号链接。
  • srwxr-xr-x:套接字文件(Socket),这里的 s 表示套接字。

在 Linux 操作系统中,有一个核心哲学理念——“一切皆文件”。这意味着几乎所有的系统资源和设备,无论是物理设备、进程、网络接口、配置项等,都可以被看作文件来进行操作。这种设计带来了统一的接口和简洁的操作方式,使得 Linux 系统变得非常灵活和强大。以下是对这一概念的详细介绍:

普通文件

  • 定义:普通文件是用户最常接触到的文件类型,通常包括文本文件、可执行文件、脚本文件等。
  • 特点:普通文件包含数据,可以被读取、写入、修改。文件系统为这些文件提供了标准的接口,如 openreadwrite 等操作。

目录 Directory

  • 定义:目录是用来存储文件和子目录的特殊文件。
  • 特点:目录本质上也是一个文件,但它存储的是文件名及其对应的 inode 信息。通过目录文件,可以方便地组织和管理系统中的文件结构。
  • 操作:可以通过 ls 列出目录内容,通过 cd 切换目录,通过 mkdir 创建新目录等。

设备文件 Device Files

  • 定义:设备文件是对硬件设备的抽象,如硬盘、键盘、显示器等。
  • 类型:设备文件分为字符设备和块设备:
    • 字符设备文件:一次处理一个字符数据,如键盘、串口设备。典型的字符设备文件在 /dev 目录下,如 /dev/tty
    • 块设备文件:一次处理大块数据,通常是存储设备,如硬盘。典型的块设备文件有 /dev/sda 等。
  • 特点:设备文件提供了对设备的标准化访问方式,可以像读写普通文件一样访问这些设备。

管道 Pipes

  • 定义:管道文件是一种特殊的文件类型,用于在两个进程之间传递数据。
  • 类型
    • 匿名管道(Anonymous Pipes):只能在有亲缘关系的进程之间使用。
    • 命名管道(Named Pipes):通过一个文件名存在于文件系统中,可以在无亲缘关系的进程间传递数据,典型例子如 FIFO 文件。
  • 特点:数据在管道中是线性流动的,写入的数据只能被一次性读取。

套接字 Sockets

  • 定义:套接字文件是一种用于网络通信的特殊文件类型。
  • 特点:套接字文件用于实现进程之间的网络通信,支持多种协议(如 TCP、UDP)。在文件系统中,套接字文件通常存储在 /var/run//tmp/ 目录下。
  • 操作:可以使用 socket 系统调用创建套接字,通过 bindlistenaccept 等调用进行网络通信。
  • 定义:符号链接是指向另一个文件或目录的特殊文件。
  • 特点:符号链接类似于 Windows 系统中的快捷方式,它不包含实际数据,而是指向目标文件。通过 ln -s 命令创建符号链接。

进程与文件

  • 定义:在 Linux 中,进程也可以通过文件接口来管理和操作。
  • 特点:每个进程在 /proc 文件系统下都有对应的目录,里面包含了该进程的各种信息,如 statuscmdlinefd(文件描述符)等。这些信息都以文件的形式存在,可以通过读取这些文件来了解进程的状态。

虚拟文件系统 Virtual Filesystem

  • 定义:虚拟文件系统(如 /proc/sys)是内核提供的接口,用于访问内核数据结构和系统状态。
  • /proc:提供进程信息和系统状态,如 CPU 信息、内存使用情况等。
  • /sys:主要用于查看和控制硬件设备及驱动相关的参数。

利用文件类型符号进行数据过滤

bash
# 过滤以 - 开头的文件,即常规文件
ls -lha ./ | grep "^-"

Linux bash 脚本可以通过:

参数描述
-e检查文件是否存在,不论文件类型是什么。
-f判断文件是否为普通文件,如文本文件、二进制文件等。
-d检查文件是否为目录(文件夹)。
-L判断文件是否为符号链接(软链接)。
-S判断文件是否为套接字文件,一般在网络通信中使用。
-c检查文件是否为字符设备文件,如终端、串口等。
-b判断文件是否为块设备文件,如硬盘、U 盘等。
bash
#!/bin/bash

FILE_PATH="/tmp/testfile"

check_file() {
    if [ -e "$FILE_PATH" ]; then
        echo "文件存在:$FILE_PATH"
    else
        echo "文件不存在:$FILE_PATH"
    fi
}

check_file
touch "$FILE_PATH"
check_file
bash
#!/bin/bash

FILE_PATH="/tmp/testfile"

check_regular_file() {
    if [ -f "$FILE_PATH" ]; then
        echo "这是一个普通文件:$FILE_PATH"
    else
        echo "不是普通文件:$FILE_PATH"
    fi
}

check_regular_file
bash
#!/bin/bash

DIR_PATH="/tmp/testdir"

check_directory() {
    if [ -d "$DIR_PATH" ]; then
        echo "这是一个目录:$DIR_PATH"
    else
        echo "不是目录:$DIR_PATH"
    fi

}

check_directory
mkdir "$DIR_PATH"
check_directory
bash
#!/bin/bash

FILE_PATH="/tmp/testfile"
LINK_PATH="/tmp/testlink"

check_symlink() {
    if [ -L "$LINK_PATH" ]; then
        echo "这是一个符号链接:$LINK_PATH -> $(readlink -f "$LINK_PATH")"
    else
        echo "不是符号链接:$LINK_PATH"
    fi
}

check_symlink
ln -s "$FILE_PATH" "$LINK_PATH"
check_symlink
bash
#!/bin/bash

SOCKET_PATH="/tmp/testsocket"

check_socket() {
    if [ -S "$SOCKET_PATH" ]; then
        echo "这是一个套接字文件:$SOCKET_PATH"
    else
        echo "不是套接字文件:$SOCKET_PATH"
    fi
}

check_socket
if [ -e "$SOCKET_PATH" ]; then
    rm "$SOCKET_PATH"
fi
socat -d TCP-LISTEN:12345,reuseaddr,fork TCP-LISTEN:12346,reuseaddr,fork >/dev/null 2>&1 & # 创建套接字,监听 12345 端口
check_socket
bash
#!/bin/bash

CHAR_DEV_PATH="/dev/ttyS0"

check_char_dev() {
    if [ -c "$CHAR_DEV_PATH" ]; then
        echo "这是一个字符设备文件:$CHAR_DEV_PATH"
    else
        echo "不是字符设备文件:$CHAR_DEV_PATH"
    fi
}

check_char_dev
# 创建字符设备文件
sudo mknod "$CHAR_DEV_PATH" c 4 64 # 4 是主设备号,64 是次设备号
check_char_dev
bash
#!/bin/bash

BLOCK_DEV_PATH="/dev/sda"

check_block_dev() {
    if [ -b "$BLOCK_DEV_PATH" ]; then
        echo "这是一个块设备文件:$BLOCK_DEV_PATH"
    else
        echo "不是块设备文件:$BLOCK_DEV_PATH"
    fi
}

check_block_dev
# 创建块设备文件
sudo mknod "$BLOCK_DEV_PATH" b 8 0 # 8 是主设备号,0 是次设备号
check_block_dev

Linux 系统中常见的目录名称

目录名称应放置文件的内容
/boot系统启动文件,如内核和启动菜单
/dev设备文件,代表系统中的硬件设备
/etc系统配置文件和启动脚本
/root管理员的个人主目录
/home用户的个人主目录
/bin基本用户命令,可在单用户模式下使用
/lib系统共享库,供 /bin/sbin 命令使用
/sbin系统管理命令,供管理员使用
/media挂载点目录,用于可移动设备
/opt第三方应用软件包
/srv服务数据目录,存放网络服务数据
/tmp临时文件目录,所有用户均可访问
/proc虚拟文件系统,提供进程和内核信息
/usr/local本地安装的软件和应用程序
/usr/sbin系统管理员使用的非基本管理命令
/usr/share共享数据,如文档和帮助文件
/var动态数据,如日志文件和临时文件
/lost+found文件系统恢复区,存放丢失的文件碎片

常见的硬件设备及其文件名称

硬件设备文件名称
IDE 设备/dev/hd[a-d]
NVMe 设备/dev/nvme[0-23]
SCSI/SATA/U盘/dev/sd[a-z]
virtio 设备/dev/vd[a-z]
软驱/dev/fd[0-1]
打印机/dev/lp[0-15]
光驱/dev/cdrom
鼠标/dev/mouse
磁带机/dev/st0/dev/ht0

常见的文件系统

文件系统特点
Ext2最早可追溯到 1993 年,是 Linux 系统的第一个商业级文件系统,基本沿袭了 UNIX 文件系统的设计标准。不包含日志读写功能,数据丢失的可能性大,通常不建议使用,顶多用于 SD 存储卡或 U 盘。
Ext3日志文件系统,预先记录写入动作的细节,然后再进行实际操作,能够在系统异常宕机时避免数据丢失并自动修复错误。硬盘容量较大时,修复时间较长,且不能 100% 保证数据不丢失。
Ext4Ext3 的改进版本,是 RHEL 6 系统的默认文件管理系统,支持的存储容量高达 1EB,支持无限多的子目录,能够批量分配 block,极大提高读写效率,主流服务器常用。
XFS高性能的日志文件系统,是 RHEL 7/8 的默认文件管理系统,宕机后可快速恢复被破坏的文件,日志功能对计算和存储性能的影响很小,支持的最大存储容量为 18EB。